home *** CD-ROM | disk | FTP | other *** search
/ Amiga Packmags / Source, The - Issue 1 (1993)(Epsilon)[WB].zip / Source, The - Issue 1 (1993)(Epsilon)[WB].adf / TextFiles / howtocode2.txt < prev   
Text File  |  1992-12-30  |  17KB  |  550 lines

  1.                  How to write demos that work (Version 2)
  2.                  ========================================
  3.  
  4.               (or How to bash the metal and get away with it)
  5.  
  6.                   by Comrade J, Share and Enjoy (retired)
  7.  
  8.  
  9. Are you fed up of downloading a new demo, running it and finding
  10. your Amiga power light sitting there flashing at you? Are you
  11. tired of the contents of your chipram flashing through the bitplane
  12. registers in a rather random fashion when you run 'Duffex's
  13. Megademo'?
  14.  
  15. Do you want demos that actually run? Because I do. I'm fed up
  16. completely with all these rubbish coders who can't do their job
  17. properly...
  18.  
  19. Now, since those long days and nights bashing away at Share and Enjoy
  20. demos I've been involved in all sorts of Amiga programming, involving
  21. new AGA machines, CD, 16-bit audio and all sorts of other
  22. wonderful things that I can't talk about, both via the OS and at a
  23. hardware level.
  24.  
  25. Most demos I've seen use similar startup code to that I was using back
  26. in 1988. Hey guys, wake up! The Amiga has changed quite a bit since
  27. then.
  28.  
  29. So. Here are some tips on what to do and what not to do:
  30.  
  31.  
  32.  
  33.  
  34.  
  35. 1. RTFM.
  36. ========
  37.  
  38. Read the F**king manuals. All of them. Borrow them off friends or from
  39. your local public library if you have to. Make sure you follow the
  40. hardware rules to the letter. If it says "Leave this bit cleared" then
  41. don't set it!
  42.  
  43. There is a lot of useful informatiton in the 'boring' OS Rom Kernal
  44. Manuals that you may be suprised to know.
  45.  
  46. Read the "General Amiga Development Guidelines" in the new (grey)
  47. Hardware Reference Manual and follow them TO THE LETTER.
  48.  
  49. Don't use self-modifying code. A common bit of code I see is:
  50.  
  51. ... in the setup code
  52.  
  53.     move.l  $6c.w,old
  54.  
  55. ... at the end of the interrupt
  56.  
  57.         movem.l    (sp)+,a0-a6/d0-d7
  58.     dc.w    $4ef9               ; jmp instruction
  59. old    dc.l    0                   ; self modifying!!!!
  60.  
  61. DONT DO THIS!
  62.  
  63. This is much better (although it still hits $6c which is not a
  64. good thing - It's much better to use AddIntServer() to call your
  65. interrupts, but more on that next time....)
  66.  
  67. ... in the setup code
  68.  
  69.     move.l  $6c.w,old
  70.  
  71. ... at the end of the interrupt
  72.  
  73.         movem.l    (sp)+,a0-a6/d0-d7
  74.     move.l    old,-(sp)        ; push old address to stack
  75.         rts
  76.  
  77. ... in your data section
  78.  
  79. old    dc.l    0
  80.  
  81.  
  82. 68020 and above processors with cache enabled often barf at the first
  83. piece of code (the cache still contains the JMP 0 instruction
  84. which isn't then altered), but the second piece works fine on the '040.
  85.  
  86.  
  87.  
  88.  
  89.  
  90. 2. Proper Copper startup.
  91. =========================
  92.  
  93. IF you are going to use the copper then this is how you should set it
  94. up. The current workbench view and copper address are stored, the
  95. system frozen, and then the copper enabled. On exit the workbench
  96. view is restored.
  97.  
  98. This guarantees your demo will run on an AGA (Amiga 1200) machine,
  99. even if set into some weird screenmode before running your code.
  100.  
  101. Otherwise under AGA, the hardware registers can be in some strange states
  102. before your code runs, beware!
  103.  
  104. The LoadView(NULL) forces the display to a standard, empty position,
  105. flushing the crap out of the hardware registers: Note. There is
  106. a bug in the V39 OS on Amiga 1200/4000 and the sprite resolution is
  107. *not* reset, you will have to do this manually if you use sprites...
  108.  
  109. Two WaitTOF() calls are needed after the LoadView to wait for both the
  110. long and short frame copperlists of interlaced displays to finish.
  111.  
  112.  
  113. I'm writing this code off the top of my head, if you spot any obvious bugs
  114. email me at the address below, or leave mail to me on Bad Dreams BBS.
  115.  
  116.                 include "exec/macros.i"
  117.                 include "exec/funcdef.i"       ; keep code simple and
  118.                 include "exec/exec_lib.i"      ; easy to read - use
  119.                 include "graphics/gfxbase.i"   ; the includes!
  120.                 include "graphics/gfx_lib.i"
  121.                 include "misc/easystart.i"     ; Allows startup from
  122.                                                ; icon
  123.  
  124.                 section mycode,code            ; need not be in chipram
  125.  
  126. StartCopper:
  127.                 move.l  4.w,a6          ; get ExecBase
  128.         lea    gfxname,a1    ; graphics name
  129.                 moveq    #0,d0        ; any version
  130.         jsr    _LVOOpenLibrary(a6)
  131.         tst.l    d0
  132.         beq     End         ; failed to open? Then quit
  133.         move.l  d0,gfxbase
  134.         move.l    d0,a6
  135.         move.l  gb_ActiView(a6),wbview
  136.                     ; store current view address
  137.                                         ; gb_ActiView = 32
  138.  
  139.                 move.w    #0,a1        ; clears full long-word
  140.         jsr     _LVOLoadView(a6) ; Flush View to nothing
  141.  
  142.                 jsr    _LVOWaitTOF(a6) ; Wait once
  143.         jsr    _LVOWaitTOF(a6) ; Wait again.
  144.  
  145.                             ; Now you can hit the copper!
  146.  
  147.         move.l    4.w,a6
  148.                 jsr    _LVOForbid(a6)  ; Suspend multitasking!
  149.  
  150.         move.l    mycopper,$dff080 ; bang it straight in.
  151.                                          ; (DO NOT F**K WITH GFXBASE!)
  152.  
  153.                 *** DO YOUR FUNKY STUFF HERE ***
  154.  
  155.  
  156. CloseDown:    move.l    4.w,a6
  157.             jsr    _LVOPermit(a6)     ; Enable multitasking
  158.  
  159.         move.l    wbview,a1
  160.         move.l    gfxbase,a6
  161.         jsr    _LVOLoadView(a6) ; Fix view
  162.  
  163.         move.l    gb_copinit(a6),$dff080     ; Kick it into life
  164.                                                ; copinit = 36
  165.         move.l    a6,a1
  166.             move.l    4.w,a6
  167.         jsr    _LVOCloseLibrary(a6) ; EVERYONE FORGETS THIS!!!!
  168.  
  169. End:        rts
  170.  
  171.         section mydata,data_C    ; keep data & code seperate!
  172.  
  173. copperlist      dc.w    $180,0          ; background black
  174.                 dc.w    $5c07,$fffe     ; wait for $5c07,$fffe
  175.                 dc.w    $180,$ff0       ; background yellow
  176.                 dc.w    $ffff,$fffe
  177.                 dc.w    $ffff,$fffe     ; Copper end (always do two
  178.                                         ; copper end cmds!)
  179.  
  180. wbview      dc.l    0
  181. wbcop       dc.l    0
  182. gfxbase     dc.l    0
  183. gfxname     dc.b    "graphics.library",0
  184.  
  185.  
  186. 3. Your code won't run from an icon.
  187. ====================================
  188.  
  189. You stick an icon for your new demo (not everyone uses the CLI!) and
  190. it either crashes or doesn't give back all the RAM it uses. Why?
  191.  
  192. Icon startup needs specific code to reply to the workbench message.
  193. With the excellent Hisoft Devpac assember, all you need to do is add
  194. the line
  195.  
  196.     include "misc/easystart.i"
  197.  
  198. and it magically works!
  199.  
  200. For those without Devpac, here is the relevent code:
  201.  
  202. ---------------------------------------------------------
  203.  
  204. * some startup code to make a Workbench execute look like the CLI
  205. * based loosely on RKM Vol 1 page 4-36
  206.  
  207. * Include this at the front of your program
  208. * after any other includes
  209. * note that this needs exec/exec_lib.i
  210.  
  211.     IFND    EXEC_EXEC_I
  212.     include    "exec/exec.i"
  213.     ENDC
  214.     IFND    LIBRARIES_DOSEXTENS_I
  215.     include    "libraries/dosextens.i
  216.     ENDC
  217.  
  218.  
  219.     movem.l    d0/a0,-(sp)        save initial values
  220.     clr.l    returnMsg
  221.  
  222.     sub.l    a1,a1
  223.     move.l    4.w,a6
  224.     jsr    _LVOFindTask(a6)        find us
  225.     move.l    d0,a4
  226.  
  227.     tst.l    pr_CLI(a4)
  228.     beq.s    fromWorkbench
  229.  
  230. * we were called from the CLI
  231.     movem.l    (sp)+,d0/a0        restore regs
  232.     bra    end_startup        and run the user prog
  233.  
  234. * we were called from the Workbench
  235. fromWorkbench
  236.     lea    pr_MsgPort(a4),a0
  237.     move.l    4.w,a6
  238.     jsr    _LVOWaitPort(A6)        wait for a message
  239.     lea    pr_MsgPort(a4),a0
  240.     jsr    _LVOGetMsg(A6)            then get it
  241.     move.l    d0,returnMsg        save it for later reply
  242.  
  243. * do some other stuff here RSN like the command line etc
  244.     nop
  245.  
  246.     movem.l    (sp)+,d0/a0        restore
  247. end_startup
  248.     bsr.s    _main            call our program
  249.  
  250. * returns to here with exit code in d0
  251.     move.l    d0,-(sp)        save it
  252.  
  253.     tst.l    returnMsg
  254.     beq.s    exitToDOS        if I was a CLI
  255.  
  256.     move.l    4.w,a6
  257.         jsr    _LVOForbid(a6)
  258.     move.l    returnMsg(pc),a1
  259.     jsr    _LVOPermit(a6)
  260.  
  261. exitToDOS
  262.     move.l    (sp)+,d0        exit code
  263.     rts
  264.  
  265. * startup code variable
  266. returnMsg    dc.l    0
  267.  
  268. * the program starts here
  269.     even
  270. _main
  271.  
  272. ---------------------------------------------------------
  273.  
  274.  
  275.  
  276.  
  277. 4. How do I tell if I'm running on an Amiga 1200/4000?
  278. ======================================================
  279.  
  280. Do *NOT* check library revision numbers, V39 OS can and does
  281. run on standard & ECS chipset machines (This Amiga 3000
  282. is currently running V39).
  283.  
  284. This code will check for AGA
  285.  
  286.         move.w    $dff07c,d0
  287.     cmp.b    #$f8,d0
  288.     bne.s    .notaga
  289.  
  290.     ; Do your funky AGA Stuff in here!
  291.  
  292. .notaga
  293.  
  294.  
  295.  
  296.  
  297.  
  298. 5. Use Relocatable Code
  299. =======================
  300.  
  301. If you write demos that run from a fixed address you should be shot.
  302. NEVER EVER DO THIS. It's stupid and completely unnecessary.
  303.  
  304. If you require bitplanes to be on a 64Kb boundary then try the
  305. following (in pseudo-code because I'm too lazy to write it in asm
  306. for you):
  307.  
  308.         for c=0 to (top of chip ram) step 65536
  309.  
  310.         if AllocAbs(c,NUMBER_OF_BYTES_YOU_WANT) == TRUE then goto ok:
  311.  
  312.     next c:
  313.  
  314.         print "sorry. No free ram. Close down something and retry demo!"
  315.         stop
  316.  
  317. ok:    Run_Outrageous_demo with mem at c
  318.  
  319. Keep your code in multiple sections. Several small sections are
  320. better than one large section, they will more easilly fit in and run
  321. on a system with fragmented memory.
  322.  
  323.  
  324.  
  325.  
  326. 6. Don't Crunch demos!
  327. ======================
  328.  
  329. Don't ever use Tetrapack or Bytekiller based packers. They are crap.
  330. Many more demos fall over due to being packed with crap packers than
  331. anything else. If you are spreading your demo by electronic means
  332. (which most people do now, the days of the SAE Demodisks are long
  333. gone!) then assemble your code, and use LHARC to archive it, you
  334. will get better compression with LHARC than with most runtime
  335. packers.
  336.  
  337. If you *have* to pack your demos, then use Powerpacker 4+, Turbo
  338. Imploder or Titanics Cruncher, which I've had no problems with myself.
  339.  
  340.  
  341.  
  342.  
  343. 7. Don't use the K-Seka assembler!
  344. ==================================
  345.  
  346. It's dead and buried. Get a life, get a real assembler. Hisoft Devpac
  347. is probably the best all-round assembler, although I use ArgAsm
  348. which is astonishingly fast.
  349.  
  350.  
  351.  
  352. 8. Don't use the hardware unless you have to!
  353. =============================================
  354.  
  355. This one is aimed particularly at utility authors. I've seen some
  356. *awfully* written utilities, for example (although I don't want
  357. to single them out as there are plenty of others) the Kefrens
  358. IFF converter.
  359.  
  360. There is NO REASON why this has to have it's own copperlist. A standard
  361. OS-friendly version opening it's own screen works perfectly (I
  362. still use the original SCA IFF-Converter), and multitasks properly.
  363.  
  364.  
  365. 9. Beware bogus input falling through to Workbench
  366. ==================================================
  367.  
  368. If you keep multitasking enabled and run your own copperlist remember
  369. that any input (mouse clicks, key presses, etc) fall through to the
  370. workbench. The correct way to get around this is to add an input
  371. server to the IDCMP food chain (see - you *do* have to read the
  372. other manuals!) at a high priority to grab all input events before
  373. workbench/cli can get to them.
  374.  
  375. Look at the sourcecode for Protracker for an excellent example of
  376. how to do the job properly. Well done Lars!
  377.  
  378.  
  379.  
  380. 10. Have fun!
  381. =============
  382.  
  383. Too many people out there (particularly the American OS-Lamic
  384. Fundamentalists) try to tell us that you should never program at a hardware
  385. level. If you're programming for fun, ignore them! But try and put
  386. a little thought into how your code will work on other machines,
  387. nothing annoys people more than downloading 400Kb of demo and then
  388. finding it blows up on their machines. I'm not naming any names, but
  389. there are quite a few groups who I have no intention of downloading
  390. their demos again because I know it's a waste of download. With
  391. the launch of the Amiga 1200 you cannot just write for 1.3 Amiga
  392. 500's any more. Let's go out there and write some shit hot demos!
  393.  
  394.  
  395. 11. Don't Publish Code you haven't checked!
  396. ===========================================
  397.  
  398. Thanks to Timo Rossi for spotting the stupid bug in my copper
  399. setup routine (using LOFList instead of copinit). Funnily enough
  400. my own setup routine uses the correct copinit code:
  401.  
  402. Please ignore the original file and use this instead.
  403.  
  404.  
  405.  
  406.  
  407. 12. Read this, it's new!
  408. ========================
  409.  
  410. A few points I've been asked to clear up:
  411.  
  412. Always use two copper end commands ie $FFFF,$FFFE,$FFFF,$FFFE.
  413. Why? I'm not sure, but it definately said in the Harwdare
  414. Ref book that you should, ISTR that some Amiga 1000's had a dodgy
  415. copper that could overrun the first Copper End. If you look
  416. at OS copperlists they all have (or at least did when I last looked!)
  417. two END commands.
  418.  
  419. The 68010 and above processors have a Vector Base Register (VBR)
  420. that allows the exception vector table to be placed anywhere in
  421. RAM, including fast ram. This gives some speed benefits to systems
  422. with this running, but at a cost.
  423.  
  424. Anything that accesses the interrupt locations directly, for example:
  425.  
  426.     move.l    $6c.w,old
  427.     move.l    MyWickedInterruptCode,$6c.w
  428.  
  429. won't work...     Unfortunately this includes 99.9% of demos.
  430.  
  431. I'm not going to tell you how to use the VBR to calculate
  432. this, if you want to learn, get the excellent book 680x0 Programming
  433. By Example, by Stan Kelly-Bootle (Howard Sams & Co). He gets paid
  434. for telling you how to do this and I don't :-)
  435.  
  436. Plus that's not the best way to use interrupts on the Amiga. You
  437. *should* use the Exec.Library function AddIntServer, but I know
  438. most of you have a theological dislike of Library routines, only
  439. opening the graphics.library to viciously poke it!
  440.  
  441. 13 Using the blitter.
  442. =====================
  443.  
  444. If you are using the blitter in your code and you are leaving the
  445. system intact (as you should) always use the graphics.library
  446. functions OwnBlitter() and DisownBlitter() to take control
  447. of the blitter. Remember to free it for system use, many system
  448. functions (including floppy disk data decoding) use the blitter.
  449.  
  450. Another big mistake I've seen is with blitter/processor timing.
  451.  
  452. Assuming that a particular routine will be slow enough that a blitter
  453. wait is not needed is silly. Always check for blitter finished, and
  454. wait if you need to.
  455.  
  456. Don't assume the blitter will always run at the same speed too. Think
  457. about how your code would run if the processor or blitter were running
  458. at 100 times the current speed. As long as you keep this in mind,
  459. you'll be in a better frame of mind for writing compatable code.
  460.  
  461.  
  462. 14 NTSC
  463. =======
  464.  
  465. As an European myself, I'm naturally biased agains the inferior video
  466. system, but even though the US & Canada have a relatively minor Amiga
  467. community compared with Europe (Sorry, it's true :-) we should still
  468. help them out, even though they've never done a PAL Video Toaster for
  469. us (sob!).
  470.  
  471. You have two options.
  472.  
  473. Firstly, you could write your code only to use the first 200 display
  474. lines, and leave a black border at the bottom. This annoys PAL owners,
  475. who rightly expect things to have a full display. It took long enough
  476. for European games writers to work out that PAL displays were better.
  477.  
  478. You could write code that automatically checked which system it is
  479. running on and ran the correct code accordingly:
  480.  
  481. (How to check: Note, this is probably not the officialy supported method,
  482. but so many weird things happen with new monitors on AGA machines that
  483. I prefer this method, it's simpler, and works under any Kickstart)
  484.  
  485.     move.l    4.w,a6          ; execbase
  486.     cmp.b    #50,PowerSupplyFrequency(a6)    ; 531(a6)
  487.     beq.s    .pal
  488.  
  489.         jmp    I'm NTSC (or more accurately, I'm running from 60Hz power)
  490. .pal    jmp    I'm PAL  (or I'm running from 50hz power).
  491.  
  492.  
  493. If people have already switched modes to PAL, or if they are running
  494. some weird software like the ICD Flicker Free Video Prefs thingy, then
  495. this completely ignores them, but that serves them right for trying
  496. to be clever :-)
  497.  
  498. Probably better would be to check VBlankFrequency(a6) [530(a6)]
  499. as well, if both are 60Hz then it's definately a NTSC machine. If
  500. one or more are 50Hz, then it's probably a better idea to run in PAL.
  501.  
  502. Now, if you want to force a machine into the other display system
  503. you need some magic pokes: Here you go (beware other bits in
  504. $dff1dc can do nasty things. One bit can reverese the polarity
  505. on the video sync, not to healthy for some monitors I've heard...)
  506.  
  507. To turn a NTSC system into PAL (50Hz)
  508.  
  509.     move.w    #32,$dff1dc        ; Magically PAL
  510.  
  511. To turn a PAL system into NTSC (60Hz)
  512.  
  513.     move.w    #0,$dff1dc        ; Magically NTSC
  514.  
  515. Remember: Not all displays can handle both display systems!
  516. Commdore 1084/1084S, Philips 8833/8852 and multisync monitors
  517. will, and very few TV's will handle PAL signals (especially
  518. if being used with a NTSC Amiga modulator). I gather that
  519. most NTSC machines are Amiga 2000's, so perhaps this isn't
  520. a problem.
  521.  
  522. So come on you NTSC users, tell us how you would prefer
  523. the demos written!
  524.  
  525.  
  526. Thanks to everyone who has replied. Any more questions, queries,
  527. or "CJ, you got it wrong again!" type mail to the email
  528. address below....
  529.  
  530.  
  531. --------------------------------------------------------------------
  532.  
  533. This text is Copyright (C) 1992 Share and Enjoy, but may be freely
  534. distributed in any electronic form.
  535.  
  536. All opinions expressed in this article are my own, and in no way
  537. reflect those of Share and Enjoy or any BBS this file may be found
  538. on.
  539.  
  540. I didn't write this for fun, I wrote it for you to use!
  541.  
  542. If you strongly disagree with anything I write, or you want to send me
  543. some source or demos to test on Amiga 1200/4000 etc, or you have
  544. questions about Amiga programming, or suggestions for future articles,
  545. or just want to chat about the best way to optimise automatic copperlist
  546. generation code, then contact me via email at:
  547.  
  548. comradej@althera.demon.co.uk or by email at Bad Dreams BBS.
  549.  
  550.